<template>
  <div class=" bg-gray-50">

    <div class="max-w-7xl mx-auto px-4 py-8">
      <div class="grid grid-cols-3 gap-8">
        <div class="col-span-2">
          <div class="bg-white p-6 rounded-lg shadow-md mb-8">
            <div class="flex items-center space-x-4 mb-6">
              <button v-if="!isAudio"
                class="flex items-center justify-center w-12 h-12 bg-black text-white rounded-full hover:bg-opacity-90 !rounded-button">
                <i class="fas fa-microphone text-xl" @click="startRecordAudio"></i>
              </button>
              <button v-if="isAudio" @click="stopRecordAudio"
                class="flex items-center justify-center w-12 h-12 bg-red-500 text-white rounded-full hover:bg-red-600 transition duration-150 ease-in-out">
                <i class="fas fa-stop text-xl animate-pulse"></i>
              </button>
              <div class="flex-1 main">
                <div class="relative">
                  <textarea   v-model="chart_text" @keydown.enter="handleKeyUp" type="textarea" placeholder="テキストまたは音声入力" 
                  style="border-right: 0px !important;height: 2.9rem;position: relative;top:.2rem;resize:none"  
                  class="w-full px-4 py-3 border border-gray-200  focus:outline-none focus:border-blue-600 text-sm inputs"/>
                  
                    <button
                    class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-blue-600 !rounded-button">
                    <el-upload class="upload-demo" action="#" :auto-upload="true" :http-request="handleMiniUpload"
                      :file-list="fileList" :with-credentials="true" list-type="picture">
                      <i class="fas fa-camera text-lg"></i>
                    </el-upload>
                  </button>
                </div>
                
              </div>
              <button type="primary" @click="send" style="margin: 0px 0px;border-left: 0px !important;height: 3rem;background: #000;
              color: #fff; border-radius: 0px !important;border-right-color: #fff !important;width: 6rem;">検索</button>
            </div>
            <div class="bg-gray-50 p-4 rounded-lg">
              <h3 class="text-lg font-medium mb-4">
              </h3>

              <div class="space-y-4 chat" ref="chatList">
                <div v-for="(chat, index) in chatHistory" :key="index">
                  <div v-if="chat.isUser && chat.type == 'text'" class="flex items-start justify-end">
                    <div class="mr-4 bg-gray-100 p-4 rounded-lg max-w-[30%]">
                      <p class="text-sm text-gray-700">{{ chat.text }}</p>
                    </div>
                    <div class="flex-shrink-0 w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center">
                      <i class="fas fa-user text-white"></i>
                    </div>
                  </div>
     
                  <div v-if="chat.isUser && chat.type == 'audio'" class="flex items-start justify-end">
                    <div class="mr-4 bg-gray-100 p-4 rounded-lg max-w-[30%]">
                    
                      <Voice :ref="'voice' + index" :id="index" :url="chat.url" ></Voice>
                    </div>
                    <div class="flex-shrink-0 w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center">
                      <i class="fas fa-user text-white"></i>
                    </div>
                  </div>
                  <div v-if="chat.isUser && chat.type == 'media'" class="flex items-start justify-end">
                    <div class="mr-4 bg-gray-100 p-4 rounded-lg max-w-[30%]">
                      <p style="margin-bottom: .5rem">{{ chat.text }}</p>
                      <img :src="media_url" alt="User Media" class="w-full rounded-lg">
                    </div>
                    <div class="flex-shrink-0 w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center">
                      <i class="fas fa-user text-white"></i>
                    </div>
                  </div>
                  <div class="flex items-start" v-if="!chat.isUser && chat.type == 'text'">

                    <div class="flex-shrink-0 w-8 h-8 bg-black rounded-full flex items-center justify-center">
                      <i class="fas fa-robot text-white"></i>
                    </div>
                    <div class="ml-4 bg-blue-50 p-4 rounded-lg max-w-[80%]">
                      <div class="mb-2">
                        <Voice v-if="chat.url" :ref="'voice' + index" :id="index" :url="chat.url"></Voice>
                        <p class="text-sm text-gray-700 mt-1">{{ chat.text }}</p>

                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="grid grid-cols-4 gap-4">
            <div @click="review"
              class="bg-white p-4 rounded-lg shadow-sm text-center hover:shadow-md transition-shadow cursor-pointer">
              <i class="fas fa-book-open text-2xl text-black mb-2"></i>
              <h3 class="text-sm font-medium">練習</h3>
            </div>
            <div class="bg-white p-4 rounded-lg shadow-sm text-center hover:shadow-md transition-shadow cursor-pointer"
              @click="to_error">
              <i class="fas fa-exclamation-circle text-2xl text-black mb-2"></i>
              <h3 class="text-sm font-medium">誤答集</h3>
            </div>
            <div class="bg-white p-4 rounded-lg shadow-sm text-center hover:shadow-md transition-shadow cursor-pointer"
              @click="to_history">
              <i class="fas fa-chart-line text-2xl text-black mb-2"></i>
              <h3 class="text-sm font-medium">解答記録</h3>
            </div>
            <div class="bg-white p-4 rounded-lg shadow-sm text-center hover:shadow-md transition-shadow cursor-pointer"
             @click="toView"
            >
              <i class="fas fa-chart-line text-2xl text-black mb-2"></i>
              <h3 class="text-sm font-medium">個別化練習</h3>
            </div>
          </div>
        </div>

        <div class="space-y-6">

          <div class="bg-white p-6 rounded-lg shadow-md h-fit">
            <h3 class="text-lg font-medium mb-4">学習データ</h3>
            <div class="space-y-6">
              <div class="p-4 bg-gray-50 rounded-lg">
                <h4 class="font-medium text-sm mb-3">今週の勉強の概要</h4>
                <div class="space-y-2">
                  <div class="flex justify-between text-sm">
                    <span class="text-gray-600">完成したの問題数</span>
                    <span class="font-medium">{{ count_total?.completed_tasks }}</span>
                  </div>
                  <div class="flex justify-between text-sm">
                    <span class="text-gray-600">今週の正解率</span>
                    <span class="font-medium">{{ count_total?.correctness_rate }}%</span>
                  </div>
                  <div class="flex justify-between text-sm">
                    <span class="text-gray-600">今週の達成率</span>
                    <span class="font-medium">{{ count_total?.completion_rate }}%</span>
                  </div>
                  <!-- <div class="flex justify-between text-sm">
                    <span class="text-gray-600">今週の勉強時間</span>
                    <span class="font-medium">{{ roundMinutes(count_total?.total_study_time) }}{{
                      isMinuteOrHour(roundMinutes(count_total?.total_study_time)) }}</span>
                  </div> -->
                </div>
              </div>


            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Recorder from 'js-audio-recorder';
import Voice from '@/components/voice.vue'
// const googleTTS = require('google-tts-api');


import { post, get } from "@/http/axios"
import { uploadFile } from "@/utils/oss";
export default {

  name: 'Home',
  components: {
    Voice
  },
  data() {
    return {
      fileList: [],
      index: 0,
      lastEnterPressTime: 0,
      // 设置一个时间间隔，例如500毫秒内按两次回车视为双击
      enterPressInterval: 500,
      files: null,
      paly_flag: [],
      isAudio: false,
      chart_text: "",
      chatHistory: [],
      speech: [],
      media_url: "",
      count_total: {},
      recorder: new Recorder({
        sampleBits: 16, // 采样位数
        sampleRate: 16000, // 采样率
        numChannels: 1, // 声道
      }),
      // audioPlayerIndex: 0, // 用于存储当前播放的音频索引

      // audioPlayers: [], // 存储音频元素的引用
    }
  },

  mounted() {
    this.chatHistory.push({
      type: 'text',
      text: "こんにちは！私はあなたの学習をサポートするAIアシスタントです！何かお困りのことがあれば、どうぞお気軽にお聞きください。テキストや音声で質問を入力したり、画像をアップロードしていただくこともできますよ！",
      isUser: false,
      index: this.index,
    });
    this.getCunts()
  },
  async created() {

  },
  // watch: {
  //   chatHistory: {
  //     handler(arr) {
  //       for (let i = 0; i < arr.length; i++) {
  //         this.$set(this.paly_flag, i, false);
  //         this.speech[i] = new Speech();
  //         this.speech[i].setLanguage("en-US"); // 设置语言
  //         this.speech[i].init().then(() => { })
  //       }
  //     },
  //     deep: true
  //   }
  // },
  methods: {
    roundMinutes(minutes) {
      return Math.round(minutes);
    },
    toView(){
      this.$router.push({path:'/user_history',query:{flag:true}})
    },
    isMinuteOrHour(value) {
      // 处理负数和非整数情况
      if (value < 0 || !Number.isInteger(value)) {
        return '無効な入力は、非負の整数を入力してください';
      }

      // 处理分钟
      if (value >= 0 && value < 60) {
        return '分';
      }

      // 处理小时，包括超过23小时但小于48小时的情况
      if (value >= 0 && value <= 23) {
        return '時間';
      } else if (value > 23 && value <= 47) {
        // 将超过24小时但小于48小时的值转换为0-23的范围
        value = value - 24;
        return '時間';
      } else if (value > 47 && value <= 71) {
        value = value - 48;
        return '時間';
      } else {
        return '時間や分の値は有効ではありません';
      }
    },
    isMinuteOrHour(value) {
      // 处理负数和非整数情况
      if (value < 0 || !Number.isInteger(value)) {
        return '無効な入力です,非負の整数を入力してください';
      }

      // 处理分钟
      if (value >= 0 && value < 60) {
        return '分';
      }

      // 处理小时，包括超过23小时但小于48小时的情况
      if (value >= 0 && value <= 23) {
        return '時間';
      } else if (value > 23 && value <= 47) {
        // 将超过24小时但小于48小时的值转换为0-23的范围
        value = value - 24;
        return '時間';
      } else if (value > 47 && value <= 71) {
        value = value - 48;
        return '時間';
      } else {
        return '時間や分の値は有効ではありません';
      }
    },
    async getCunts() {
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      let data = await get("/get_week_success_task")
      loading.close();
      this.count_total = data.data.data
    },
    to_history() {
      this.$router.push('/history')
    },
    to_error() {
      this.$router.push('/error_list')
    },
    async handleMiniUpload(params) {

      const file = params.file
      console.log(file)

      let formData = new FormData();
      formData.append("file", file);
      let data = await post("/upload_img", formData)
      this.files = data.data.data
      this.fileList.push({
        url: data.data.data,
        name: file.name
      })

    },
    // playAi(text, index) {
    //   for (let i = 0; i < this.speech.length; i++) {
    //     if (this.speech[i]) {
    //       this.$set(this.paly_flag, i, false);
    //       this.speech[i].cancel()
    //     }
    //   }
    //   if (this.speech[index] && this.speech[index].paused) {
    //     this.speech[index].resume();
    //   }
    //   this.speech[index].speak({
    //     text: text, // 要播放的文本

    //     listeners: {
    //       onend: () => {
    //         this.$set(this.paly_flag, index, false);
    //         this.paly_flag[index] = false
    //         this.speech[index].cancel()
    //       }
    //     }
    //   }).then(() => {
    //     console.log("读取成功");
    //   });
    //   this.$set(this.paly_flag, index, true);

    // },
    // pauseAi(index) {
    //   this.$set(this.paly_flag, index, false);
    //   this.speech[index].pause();
    // },
    // playAudio(index) {
    //   const audioElements = this.$refs.audioPlayer;
    //   if (audioElements) {
    //     // 停止其他音频播放
    //     audioElements.forEach((element, i) => {
    //       if (i !== index) {
    //         element.pause();
    //       }
    //     });
    //     // 播放点击的音频
    //     audioElements[index].play();
    //   }
    // },
    review() {
      this.$router.push('/question_type')
    },
    // 播放指定的音频消息
    // 开始录音
    startRecordAudio() {
      Recorder.getPermission().then(
        () => {
          this.isAudio = true;
          this.recorder.start(); // 开始录音
          console.log("録音を始めます")
        },
        (error) => {
          console.log(error)
          this.$message({
            message: "このページにマイクを使用させていただきます",
            type: "info",
          });
          console.log(`${error.name} : ${error.message}`);
        }
      );
    },
    // 停止录音
    async stopRecordAudio() {
      this.isAudio = false;
      this.recorder.stop();
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      await this.uploadAndAddToChatList()
      loading.close();
    },
    startRecording() {
      this.recorder = new Recorder()
      Recorder.getPermission().then(() => {
        console.log('録音を始めます')
        this.recorder.start() // 开始录音
      }, (error) => {
        this.$message({
          message: 'このページにマイクを使用させていただきます',
          type: 'info'
        })
        console.log(`${error.name} : ${error.message}`)
      })
    },
    dataURLtoBlob(dataurl) {
      var arr = dataurl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], {
        type: mime,
      });
    },
    // 上传录音并添加到聊天列表
    async uploadAndAddToChatList() {
      try {
        const wavBlob = this.recorder.getWAVBlob();
        const formData = new FormData();
        const fileOfBlob = new File([wavBlob], new Date().getTime() + '.wav', { type: 'audio/wav' });
        formData.append('file', fileOfBlob);
        // 调用上传API
        let res = await uploadFile(fileOfBlob);
        // 上传成功后，将消息添加到聊天列表
        this.addMessageToChatList({
          type: 'audio',
          url: res,
          timestamp: new Date().toISOString(),
          index: this.index
        });

        this.index++
        this.chatHistory.push({
          type: "text",
          text: "識別中です...",
          isUser: false,
          index: this.index
        })
        this.scrollToBottom()
        const response = await post("/audioToText", formData);
        if (response && response.data && response.data.data) {
          //  let url = googleTTS.getAudioUrl(this.chatHistory[this.chatHistory.length - 1].text, { lang: 'zh-CN' })
          //          let base64 =await googleTTS.getAudioBase64(this.chatHistory[this.chatHistory.length - 1].text, {
          //   lang: 'en',
          //   slow: false,
          //   host: 'https://translate.google.com',
          //   timeout: 10000,
          // })
          // alert(base64)
          // let audioBlob = this.dataURLtoBlob(base64);
          // let blobUrl = window.URL.createObjectURL(audioBlob);
          let url = await this.synthesizeSpeech(response.data.data)
          
          this.$set(this.chatHistory, this.chatHistory.length - 1, { ...this.chatHistory[this.chatHistory.length - 1], text: response.data.data, isUser: false, type: 'text',url: url });
          this.scrollToBottom()
        }
      } catch (error) {
        this.$set(this.chatHistory, this.chatHistory.length - 1, { ...this.chatHistory[this.chatHistory.length - 1], text: "接続タイムアウトです", isUser: false, type: 'text' });

        console.error('アップロードに失敗しました:', error);
      }
    },
    // 添加消息到聊天列表
    addMessageToChatList(message, index) {
      this.chatHistory.push({
        type: "audio",
        url: message.url,
        isUser: true,
        index: index
      });



      // 可选：滚动到聊天列表底部
      this.scrollToBottom();
    },
    // 滚动到聊天列表底部
    scrollToBottom() {
      this.$nextTick(() => {
        const chatListElement = this.$refs.chatList;
        chatListElement.scrollTop = chatListElement.scrollHeight;
      });
    },
    handleKeyUp(event) {
      const now = Date.now();
      if (!event.shiftKey) {
        event.preventDefault(); 
      }
      // 检查当前按键是否是回车键
      if (event.key === 'Enter') {
        // 如果两次回车键的时间间隔小于设定的时间间隔，则认为是双击回车
        if (now - this.lastEnterPressTime < this.enterPressInterval) {
          this.send();
        } else {
          // 如果不是，则更新时间戳
          this.lastEnterPressTime = now;
        }
      }
    },
    async send() {

      if (this.chart_text == "") {
        this.$message({
          message: '質問を入力してください',
          type: 'warning'
        });
        return
      }

      if (this.chatHistory[this.chatHistory.length - 1].text == "識別中です...") {
        this.$message({
          message: 'コンテンツを作成中です。',
          type: 'warning'
        });
        return
      }
      if (this.chart_text == "" && this.fileList.length > 0) {
        this.$message({
          message: '内容の入力をお願いします',
          type: 'warning'
        });
        return
      }

      if (this.fileList.length > 0) {
        this.chatHistory.push({
          text: this.chart_text,
          isUser: true,
          type: "media"

        });


        this.media_url = this.fileList[0].url;
        this.fileList = []

        let obj = {
          url: this.files,
          query: this.chart_text
        }
        this.chatHistory.push({
          type: "text",
          text: "識別中です...",
          isUser: false
        })
        this.scrollToBottom()
        try {
          let data = await post("/uploadFile", { ...obj })
          let url = await this.synthesizeSpeech(data.data.data)
          this.$set(this.chatHistory, this.chatHistory.length - 1, { ...this.chatHistory[this.chatHistory.length - 1], text: data.data.data, isUser: false, type: 'text' ,url: url});

          this.scrollToBottom()

          this.chart_text = "";
        } catch (error) {
          this.$set(this.chatHistory, this.chatHistory.length - 1, { ...this.chatHistory[this.chatHistory.length - 1], text: "接続タイムアウトです", isUser: false, type: 'text' });
        }

      } else {
        this.chatHistory.push({
          text: this.chart_text,
          isUser: true,
          type: "text"

        });
        this.scrollToBottom()

        this.chatHistory.push({
          type: "text",
          text: "識別中です...",
          isUser: false
        })
        try {
          let data = await post("/chat", { "query": this.chart_text })
          let url = await this.synthesizeSpeech(data.data.data)
          console.log(url)
          this.$set(this.chatHistory, this.chatHistory.length - 1, { ...this.chatHistory[this.chatHistory.length - 1], text: data.data.data, isUser: false, type: 'text', url: url });
          this.scrollToBottom()
          this.chart_text = "";
        } catch (error) {
          this.$set(this.chatHistory, this.chatHistory.length - 1, { ...this.chatHistory[this.chatHistory.length - 1], text: "接続タイムアウトです", isUser: false, type: 'text' });

        }
      }

    },
    async synthesizeSpeech(text) {
      const audioData = await post("https://texttospeech.googleapis.com/v1/text:synthesize?key=AIzaSyD9svMNBcCUbDn86-QdHCtUrY2Hp1Nn2V8",
        {
          input: {
            text: text
          },
          voice: {
            "languageCode": "ja-JP",
            "name": "ja-JP-Wavenet-A",
            "ssmlGender": "FEMALE",
          },
          audioConfig: {
            "audioEncoding": "MP3",
            "speakingRate": 1.0,
            "pitch": 0,
          }
        }
      )
      const audioContent = audioData.data.audioContent;
      const audioDatas = Uint8Array.from(atob(audioContent), c => c.charCodeAt(0)); // Base64 解码

      const formData = new FormData();
      const blob = new Blob([audioDatas.buffer], { type: 'audio/mp3' });
      console.log(blob)
      formData.append('file', blob, 'output.mp3');
      let qq = await post("/chatAudioUpload", formData)
      return qq.data.data
    }
  }
}
</script>

<style scoped>
.main /deep/ .el-upload-list__item-name {
  display: none !important;
}

.main /deep/ .el-upload-list--picture .el-upload-list__item-thumbnail {
  margin: 0px 0px !important;
  width: 5rem !important;
  height: 3.5rem !important;
}

.main /deep/ .el-upload-list--picture .el-upload-list__item {
  width: 5rem;
  padding: 1rem 0.5rem !important;
  float: right;
}

.main /deep/ .text-gray-400 {
  width: 2.5rem;
  height: 2.5rem !important;
}

.main /deep/ .el-upload-list {
  clear: both !important;
}

.main /deep/ .el-upload .el-upload--picture {
  position: absolute !important;
  right: 0px !important;
}

.main /deep/ .el-upload {
  float: right;
}

.inputs {

  padding-right: 3rem;
}

.main .upload-demo {
  cursor: auto !important;
  height: 8rem;
  position: absolute !important;
  top: 0.5rem;
  right: 0rem;
}

.chat {
  max-height: 20rem;
  min-height: 20rem;
  overflow-y: auto;
}

.play {
  cursor: pointer;
}

.uls {
  display: none;
  background-color: #fff;
  padding: 10px;
  position: absolute;
  top: 60px;
  left: 0;

  width: 150px;
  border: 1px solid #ccc;
}


.chat ::-webkit-scrollbar:horizontal {
  height: var(--horizontal-scrollbar-track-width) !important;
}

.chat ::-webkit-scrollbar:vertical {
  width: var(--vertical-scrollbar-track-width) !important;
}

.chat ::-webkit-scrollbar-track:vertical {
  background: var(--vertical-scrollbar-track-color) !important;
  border-radius: var(--vertical-scrollbar-track-radius) !important;
}

.chat ::-webkit-scrollbar-track:horizontal {
  background: var(--horizontal-scrollbar-track-color) !important;
  border-radius: var(--horizontal-scrollbar-track-radius) !important;
}

/*.chat ::-webkit-scrollbar-thumb {*/
/*  background-color: var(--horizontal-scrollbar-thumb-color);*/
/*  border-radius: var(--horizontal-scrollbar-track-radius);*/
/*  border: var(--horizontal-scrollbar-thumb-border);*/
/*}*/

/* 纵向滚动条样式 */
.chat ::-webkit-scrollbar-thumb:vertical {
  background-color: var(--vertical-scrollbar-thumb-color) !important;
  border-radius: var(--vertical-scrollbar-thumb-radius) !important;
  border: var(--vertical-scrollbar-thumb-border) !important;
  border-top-width: 0 !important;
  border-bottom-width: 0 !important;
}


.chat ::-webkit-scrollbar-corner {
  background: none !important;
  ;
}

.uls li {
  z-index: 99999;
  list-style: none;
  margin-bottom: 5px;
  cursor: pointer;
}

button:focus+ul {
  display: block;
}

.dvs {
  position: relative;
}
.items-center /deep/ .el-button:hover {
  color: #fff !important;
  background-color: #000 !important; /* 鼠标悬停时改变背景颜色 */
}
</style>
